package com.musicgeek.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * Helper class for load properties files form classpath.
 */
public abstract class PropertyLoader {
	// Conditional compilation constants for toggle throw
	// IllegalArgumentException on load resource failure
	private static final boolean THROW_ON_LOAD_FAILURE = true;
	// Property files suffix.
	private static final String SUFFIX = ".properties";

	/**
	 * A convenience overload of {@link #loadProperties(String, InputStream)}
	 * that uses the specific classloader to get inputstream.
	 */
	public static Properties loadProperties(String name, ClassLoader loader)
			throws IOException {
		checkIfNullName(name);
		// No leading "/" (all names are absolute)
		if (name.startsWith("/"))
			name = name.substring(1);
		name = nameRevise(name);
		InputStream in = loader.getResourceAsStream(name);
		return loadProperties(name, in);
	}

	/**
	 * A convenience overload of {@link #loadProperties(String, ClassLoader)}
	 * that uses the system classloader to get resource inputstream.
	 */
	public static Properties loadProperties(String name) throws IOException {
		ClassLoader loader = ClassLoader.getSystemClassLoader();
		return loadProperties(name, loader);
	}

	/**
	 * A convenience overload of {@link #loadProperties(String, InputStream)}
	 * that uses the specific class to get resource inputstream.
	 */
	public static Properties loadProperties(String name, Class<?> cls)
			throws IOException {
		checkIfNullName(name);
		name = nameRevise(name);
		InputStream in = cls.getResourceAsStream(name);
		return loadProperties(name, in);
	}

	/**
	 * @param name
	 *            classpath resource name [may not be null]
	 * 
	 * @param in
	 *            InputStream form which to load the resource
	 * 
	 * @return resource converted to java.util.Properties [may be null if the
	 *         resource was not found and THROW_ON_LOAD_FAILURE is false]
	 * 
	 * @throws IllegalArgumentException
	 *             if the resource was not found and THROW_ON_LOAD_FAILURE is
	 *             true
	 */
	private static Properties loadProperties(String name, InputStream in)
			throws IOException {
		Properties result = null;

		try {
			// Returns null on lookup failures:
			result = new Properties();
			result.load(in);
		} catch (IOException e) {
			if (THROW_ON_LOAD_FAILURE) {
				throw new IllegalArgumentException("Could not load [" + name
						+ "] as a classloader resource");
			} else {
				result = null;
			}
		} catch (NullPointerException en) {
			throw new NullPointerException("Could not found resource [" + name
					+ "]");
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					throw new IOException("Close InputStream fail");
				}
			}
		}
		return result;
	}

	public static String nameRevise(String name) {
		if (name.endsWith(SUFFIX))
			name = name.substring(0, name.lastIndexOf(".properties"));

		name = name.replace('.', '/');
		name = name.concat(SUFFIX);

		return name;
	}

	private static void checkIfNullName(String name) {
		if (name == null)
			throw new IllegalArgumentException("Null Input: name");
	}

	/*
	 * Load from ResourceBundle if you want to take advantage to the
	 * localization support built into java.util.ResourceBundle. Also, Java
	 * internally resource caches
	 * 
	 * @param name classpath resource name [may not be null]
	 * 
	 * @param loader classloader through which to load the resource
	 * 
	 * @return resource converted to java.util.Properties [may be null if the
	 * resource was not found and THROW_ON_LOAD_FAILURE is false]
	 * 
	 * @throws IllegalArgumentException if the resource was not found and
	 * THROW_ON_LOAD_FAILURE is true
	 */
	public static Properties loadPropertiesFromResourceBundle(String name,
			ClassLoader loder) {
		checkIfNullName(name);

		return null;
	}

	/**
	 * A convenience overload of
	 * {@link #loadPropertiesFromResourceBundle(String, ClassLoader)} that uses
	 * the specific class's classloader.
	 */
	public static Properties loadPropertiesFromResourceBundle(String name,
			Class<Object> cls) {
		ClassLoader loader = cls.getClassLoader();
		return null;
	}

	/**
	 * A convenience overload of {@link #loadProperties(String, ClassLoader)}
	 * that uses the application's loader.
	 */
	public static Properties loadPropertiesFromResourceBundle(String name)
			throws IOException {
		ClassLoader loader = ClassLoader.getSystemClassLoader();
		return null;
	}

}
